<?php
/**
 * excel 上传，下载类
 * @author 老牛
 *
 */
class Excel {
	/**
	 * 构造，
	 * @author 老牛
	 * @return unknown_type
	 */
	function __construct() {
	
	}
	
	/**
	 * 析构
	 * @author 老牛
	 * @return unknown_type
	 */
	function __destruct() {
	}
	
	/**
	 * 解析上传的csv文件
	 * $keys =  array('key1', 'key2', ...);
	 * $return = array( array('key1'=>field1, 'key2'=>field2, ...), ....)
	 *
	 * @author 老牛
	 * @param $keys
	 * @param $file 文件名
	 * @return $return
	 */
	function parseCsvWithKeys($keys, $file) {
		
		$array = null; // 二维数组，每个数组是一条csv数据
		if (! file_exists ( $file )) {
			return 'no file!';
		}
		
		$cnt = count ( $keys );
		
		$lines = file ( $file );
		if (! empty ( $lines )) {
			$titles = array_shift ( $lines );
			foreach ( $lines as $line ) {
				$i = 0;
				$line = trim ( $line, "\r\n" );
				if (empty ( $line ))
					continue;
				$linArr = $this->str_getcsv ( $line );
				
				$lineArray = array ();
				while ( $i < $cnt ) {
					//$lineArray[$keys[$i]] = trim($linArr[$i],'"');
					//modify by sunhongjing 增加对字符编码的判断。全部转成utf-8
					$k = $this->getUtf8Str ( $keys [$i] );
					$lineArray [$k] = $this->getUtf8Str ( trim ( $linArr [$i], '"' ) );
					$i ++;
				}
				$array [] = $lineArray;
			}
		} else {
			return false;
		}
		return $array;
	}
	
	/**
	 * 使用csv文件的第一行作为返回字典的keys
	 * @author 老牛
	 * @param $file
	 * @param $keys 自定义的 keys
	 * @return unknown_type
	 */
	function parseCsv($file, $keys = null) {
		if (! empty ( $keys )) {
			return $this->parseCsvWithKeys ( $keys, $file );
		}
		$lines = file ( $file );
		if (! empty ( $lines )) {
			$titles = array_shift ( $lines );
			$titles = str_replace ( "\n", '', $titles );
			$titles = str_replace ( "\r", '', $titles );
			$titles = str_replace ( "\r\n", '', $titles );
			$keys = explode ( ',', $titles );
		}
		return $this->parseCsvWithKeys ( $keys, $file );
	}
	/*
	 *生成CSV
	 *@param array 输入数组
	 *@param bool 是否下载
	 *@append array 在头或尾追加数据
	 */
	function exportCSV($array, $download = true, $filename = '', $append = array(), $encode = 'utf-8') {
		$ret = '';
		$filename = empty ( $filename ) ? date ( 'Ymd' ) : $filename;
		if ($download) {
			header ( 'Content-Description: File Transfer' );
			header ( "Pragma: public" ); // required
			header ( "Expires: 0" );
			header ( "Pragma: no-cache" );
			header ( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
			header ( "Cache-Control: private", false ); // required for certain browsers
			header ( "Content-Transfer-Encoding: binary" );
			header ( "Content-type: text/csv;" );
			header ( "Content-Disposition: attachment; filename=" . basename ( $filename . '.csv' ) );
		
		}
		if ($array) {
			$header = array_keys ( $array [0] );
			array_unshift ( $array, $header );
		}
		if (! empty ( $append )) {
			$header2 = array_keys ( $append [0] );
			array_unshift ( $append, $header2 );
			array_unshift ( $append, $append [100] );
			$array = array_merge ( $array, $append );
		}
		foreach ( $array as $row ) {
			$rc = array ();
			foreach ( $row as $cell ) {
				$cell = str_replace ( '"', '""', $cell );
				$rc [] = '"' . $cell . '"';
			}
			$rc = implode ( ',', $rc );
			if ($download) {
				//add by sunhongjing 2011-03-13  增加了utf8的头
				if ('utf-8' == $encode) {
					$out = chr ( 239 ) . chr ( 187 ) . chr ( 191 ); //utf-8 header
				} else {
					$out = '';
				}
				echo $out . "$rc\r\n";
			} else {
				$ret .= "$rc\n";
			}
		}
		return $ret;
	}


	
	/**
	 * 为export分出来的功能
	 * @author 老牛
	 * @param $num
	 * @return unknown_type
	 */
	static function cell($num) {
		$index = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' );
		if ($num > 25) {
			$t = floor ( $num / 26 ) - 1;
			$out = $index [$t];
			$out .= $index [$num - ($t + 1) * 26];
			return $out;
		} else
			return $index [$num];
	
	}
	
	/**
	 * 将csv字符串解析成数组
	 * @author 老牛
	 * @param $row csv 字符串
	 * @param $delimiter 字段分隔符
	 * @param $enclouse 字段包围符号
	 * @param $escape  csv字符串内的转义标志
	 * @return array
	 */
	function str_getcsv($row, $delimiter = ',', $enclouse = '"', $escape = '\\') {
		$aims = array ();
		if (empty ( $row ))
			//return  $aims;
			

			$i = 0;
		$field = '';
		$row = trim ( $row );
		$len = strlen ( $row );
		$isExcaped = false;
		$hasEnclouse = false;
		while ( $i < $len ) {
			// 获得当期字符串
			$str = substr ( $row, $i, 1 );
			
			// 获得前一个字符串，
			if ($i != 0) {
				$preStr = substr ( $row, $i - 1, 1 );
			} else { // 如果当前为字符串的开始，则获得第一个字符
				$preStr = $str;
			}
			
			// 将转义符号去掉
			if ($str == $escape) {
				$str = '';
			}
			// 标注当期字符是否使用了转义
			if ($preStr == $escape) {
				$isExcaped = true;
			} else {
				$isExcaped = false;
			}
			
			// 如果当前字符没有使用转义，并且是字段分隔符号
			if ($str == $enclouse and ! $isExcaped) {
				// 打开/关闭 字段包围符号 标志
				$hasEnclouse = ! $hasEnclouse;
				// 并且将字段包围符号去掉
				$str = '';
			}
			
			// 如果当前字符为字段分隔符，并且字段包围符号为关闭
			if ($str == $delimiter and ! $hasEnclouse) {
				// 收割这个字段
				$aims [] = $field;
				$field = '';
			} else {
				// 否则，收编这个字符
				$field .= $str;
			}
			$i ++;
		}
		// 不内能让最后一个字段掉队
		$aims [] = $field;
		
		return $aims;
	}
	
	/**
	 * 
	 * @author 老牛
	 * @param $data
	 * @param $fileCharset	输出文件编码 例：UTF-8 
	 * @return unknown_type
	 */
	public function downloadExcel($data,$file_nm='exceldownload_', $fileCharset = 'UTF-8') {
		ini_set ( 'memory_limit', '1000M' );
		//ob_start();
		//var_dump(ob_get_length ());exit;
		$ob_active = ob_get_length () !== false;
		while ( $ob_active ) {
			ob_end_clean ();
			$ob_active = ob_get_length () !== false;
		} //清除ob
		$header = true;
		$fileName = 'tmp'; //. $this->getMd5Id ();
		$fp = fopen ( $fileName, 'w' );
		
		if ($fileCharset == 'UTF-8') {
			fputs ( $fp, chr ( 239 ) . chr ( 187 ) . chr ( 191 ) ); //写入utf-8头
		}
		
		$vdata = array ();
		foreach ( $data as $k => $row ) {
			foreach ( $row as $key => $col ) {
				$vdata [$k] [$key] = $col;
			}
		}
		
		foreach ( $vdata as $perRow ) {
			if ($header) {
				$ikeys = array_keys ( $perRow );
				
				if ($fileCharset != 'UTF-8') {
					foreach ( $ikeys as &$ik ) {
						$ik = mb_convert_encoding ( $ik, $fileCharset, "UTF-8" );
					}
				}
				fputcsv ( $fp, $ikeys );
				$header = false;
			}
			
			$ivalues = array_values ( $perRow );
			if ($fileCharset != 'UTF-8') {
				foreach ( $ivalues as &$iv ) {
					$iv = mb_convert_encoding ( $iv, $fileCharset, "UTF-8" );
				}
			}
			
			//l('Xfunc')->encode($ivalues,'UTF-8','GBK');
			fputcsv ( $fp, $ivalues );
		
		}
		
		header ( 'Content-Description: File Transfer' );
		header ( "Pragma: public" ); // required
		header ( "Expires: 0" );
		header ( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
		header ( "Cache-Control: private", false ); // required for certain browsers
		header ( "Content-Transfer-Encoding: binary" );
		header ( "Content-type: text/csv;" );
		header ( "Content-Length: " . filesize ( $fileName ) );
		   header ( "Content-Disposition: attachment; filename=\"".$file_nm . ".csv\";" );
	
		readfile ( $fileName );
	}
	/**
	 *@author 老牛
	 * 生个md5唯一id
	 * 
	 * */
	public function getMd5Id() {
		return md5 ( uniqid ( rand (), true ) );
	}
	/**
	 * 
	 * @author 老牛
	 * @date 2011-8-24
	 * 
	 * 
	 */
	public function getUtf8Str($str) {
		$isgbk = mb_check_encoding ( $str, 'gbk' );
		if ($isgbk) {
			$str = mb_convert_encoding ( $str, 'utf-8', 'GBK' );
		}
		return $str;
	}
}
